<?php

namespace Core\Common\Route;

use Core\Common\Base\Config;
use Core\Common\Util\Utils;

/**
 * Description of Request
 *
 * @author baiyang
 */
class Request
{
    const DEBUG = 110;
    const HTTP = 1;
    const REDIS = 2;
    const WEBSOCKET = 3;

    //存储类似$_SERVER中的数据
    private static $server = [];
    //GET数据
    private static $get = [];
    //POST数据
    private static $post = [];
    //COOKIE数据
    private static $cookie = [];
    //原始POST数据, 非application/x-www-form-urlencoded, multipart/form-data
    private static $raw = null;
    //tcp协议, websocket使用的指令，类似$_SERVER['REQUEST_URI']
    private static $cmd = null;
    //临时存储的本次请求的数据
    private static $registry = null;
    private static $type = self::HTTP;

    // argus 系统 span 自增 ID，每次请求设置为 0，对外发起一次 HTTP 请求，自增一次
    private static $argusIndex = 0;

    // 标识当前是否是从 mars 系统过来的压测流量
    private static $mars = null;

    public static function reset()
    {
        self::$server = [];
        self::$get = [];
        self::$post = [];
        self::$cookie = [];
        self::$type = self::HTTP;
        self::$raw = null;
        self::$registry = null;
        self::$cmd = null;
        self::$argusIndex = 0;
        self::$mars = null;
    }

    /*
     * 是否为调试模式
     */

    public static function inDebug()
    {
        if (self::get('__SQKB_DEBUG__') == self::DEBUG) {
            return true;
        }
        return false;
    }

    public static function setHttp()
    {
        self::$type = self::HTTP;
    }

    public static function setRedis()
    {
        self::$type = self::REDIS;
    }

    public static function setWebsocket()
    {
        self::$type = self::WEBSOCKET;
    }

    public static function type()
    {
        return self::$type;
    }

    public static function server($k = null, $v = null)
    {
        if (is_null($v)) {
            if (empty(self::$server) && 'cli' != php_sapi_name()) {//php-fpm
                self::$server = $_SERVER;
            }
            if (is_null($k)) {
                return self::$server;
            }
            if ($k == 'REQUEST_TIME') {
                return self::requestTime();
            }
            return self::$server[$k] ?? null;
        }
        self::$server[$k] = $v;
    }

    public static function get($k = null, $v = null)
    {
        if (is_null($v)) {
            if (empty(self::$get) && 'cli' != php_sapi_name()) {//php-fpm
                self::$get = $_GET;
            }
            if (is_null($k)) {
                return self::$get;
            }
            return self::$get[$k] ?? null;
        }
        self::$get[$k] = $v;
    }

    public static function post($k = null, $v = null)
    {
        if (is_null($v)) {
            if (empty(self::$post) && 'cli' != php_sapi_name()) {//php-fpm
                self::$post = $_POST;
            }
            if (is_null($k)) {
                return self::$post;
            }
            return self::$post[$k] ?? null;
        }
        self::$post[$k] = $v;
    }

    public static function cookie($k = null, $v = null)
    {
        if (is_null($v)) {
            if (empty(self::$cookie) && 'cli' != php_sapi_name()) {//php-fpm
                self::$cookie = $_COOKIE;
            }
            if (is_null($k)) {
                return self::$cookie;
            }
            return self::$cookie[$k] ?? null;
        }
        self::$cookie[$k] = $v;
    }

    /**
     * 设置或获取原始请求数据, (非form)请求
     * @param mixed $content
     * @return type 参数为空为获取，不为空为设置
     */
    public static function raw($content = null)
    {
        if (empty($content)) {
            return self::$raw;
        }
        self::$raw = $content;
    }

    /**
     * 存储或者获取这次请求的临时数据
     * @param type $key
     * @param type $val
     * @return type
     */
    public static function registry($key = null, $val = null)
    {
        if (is_null($val)) {
            if (is_null($key)) {
                return self::$registry;
            }
            return self::$registry[$key] ?? null;
        }
        self::$registry[$key] = $val;
    }

    /**
     * 设置请求的命令, 用于TCP(Redis), WebSocket
     * @param type $cmd
     */
    public static function setCmd($cmd)
    {
        self::$cmd = $cmd;
    }

    /**
     * HTTP获取REQUEST_URI, 非TCP返回请求的指令
     * @return type
     */
    public static function uri()
    {
        if (self::$type != self::HTTP) {
            return self::$cmd;
        }
        return self::server('REQUEST_URI') ?? '';
    }

    /**
     * 请求时间
     * @return type
     */
    public static function requestTime()
    {
        if (!isset(self::$server['REQUEST_TIME'])) {
            self::$server['REQUEST_TIME'] = time();
        }
        return self::$server['REQUEST_TIME'];
    }

    public static function method()
    {
        return self::$server['REQUEST_METHOD'] ?? '';
    }

    public static function isHttp2()
    {
        return self::server('SERVER_PROTOCOL') === 'HTTP/2' ? true : false;
    }

    public static function isGrpc()
    {
        return self::server('HTTP_CONTENT_TYPE') === 'application/grpc' ? true : false;
    }

    public static function userAgent()
    {
        return self::$server['HTTP_USER_AGENT'] ?? '';
    }

    public static function traceId()
    {
        return self::$server['HTTP_X_SQKB_TRACE_ID'] ?? (self::$server['X_SQKB_TRACE_ID'] ?? '');
    }

    public static function spanId()
    {
        return self::$server['HTTP_X_SQKB_ARGUS_SPAN_ID'] ?? (self::$server['X_SQKB_ARGUS_SPAN_ID'] ?? '0.1');
    }

    public static function nextSpanId()
    {
        return self::spanId() . '.' . self::incrArgusIndex();
    }

    public static function isArgusSimple()
    {
        if(!defined('CORE_CONFIG_PATH')) {
            return false;
        }
        $argusConfig = Config::config('argus');
        $argusSwitch = $argusConfig['on'] ?? true;

        if (!$argusSwitch) {
            return false;
        }

        return (isset(self::$server['HTTP_X_SQKB_ARGUS_IS_SAMPLE'])
                && self::$server['HTTP_X_SQKB_ARGUS_IS_SAMPLE'] == 'true')
            || (isset(self::$server['X_SQKB_ARGUS_IS_SAMPLE'])
                && self::$server['X_SQKB_ARGUS_IS_SAMPLE'] == 'true');
    }

    public static function incrArgusIndex()
    {
        return ++self::$argusIndex;
    }

    /**
     * 当前请求是否是否属于压测流量
     * @return boolean true代表当前是压测流量，false代表是正常流量
     */
    public static function isRunningInMars()
    {
        if (is_null(self::$mars)) {
            self::$mars = self::$server['HTTP_X_SQKB_MARS'] ?? (self::$server['X_SQKB_MARS'] ?? '');
            if (empty(self::$mars)) {
                return false;
            }
        }
        return self::$mars == "1";
    }

    /**
     * 手动设置压测标记，用于单元测试
     * @param [type] $flag [description]
     */
    public static function setMarsFlag($flag) {
        self::$mars = (string)$flag;
    }

    public static function requestSize()
    {
        $reqSize = 0;
        if ('GET' == Request::method()) {
            $reqSize = strlen(Request::server('QUERY_STRING'));
        } else {
            if ('' !== Request::method()) {
                $reqSize = Request::server('HTTP_CONTENT_LENGTH') ?? 0;
            } else {
                $reqSize = strlen(self::$raw);
            }
        }
        return $reqSize;
    }

    /**
     * 类似于$_REQUEST
     * @param type $k
     * @return type
     */
    public static function request($k = null)
    {
        if (!is_null(self::$raw) && false !== self::$raw) {//json数据
            if (is_array(self::$raw)) {//websocket
                if (is_null($k)) {
                    return self::$raw;
                }
                return self::$raw[$k] ?? null;
            }
            //raw(非form)请求

            $arr = json_decode(self::$raw, true);
            $arr['user_ip'] = Utils::getClientIp();

            if (is_null($k)) {
                return $arr;
            }

            return $arr[$k] ?? null;
        }
        if (is_null($k)) {
            return self::get() + self::post() + ['user_ip' => Utils::getClientIp()];
        }
        return self::get($k) ?? self::post($k);
    }
}
